// Package dao
// @Author zhongxc
// @Date 2024/7/23 15:44:00
// @Desc
package dao

import (
	"context"
	"errors"
	"fmt"
	"gorm.io/gorm"
	"math"
	"strconv"
	"strings"
	"vben-admin/pkg/dao/internal"
	"vben-admin/pkg/model"
	"vben-common/msdb"
	"vben-common/msdb/gorms"
)

type UserDao struct {
	conn    *gorms.GormConn
	columns *internal.UserColumns
}

func NewUserDao(db *msdb.MsDB) *UserDao {
	return &UserDao{
		conn:    gorms.New(db.Conn),
		columns: internal.NewUserColumns(),
	}
}

func (u *UserDao) getSession(ctx context.Context) *gorm.DB {
	return u.conn.Session(ctx)
}

// CreateUser
// @Description: 创建用户
// @receiver u
// @param ctx
// @param user
// @return error
func (u *UserDao) CreateUser(ctx context.Context, user *model.UserModel) error {
	err := u.getSession(ctx).
		Omit(model.IgnoreUpdatedAt, model.IgnoreUpdatedBy, model.IgnoreCreatedAt, model.IgnoreDeletedBy).
		Create(user).
		Error
	return err
}

// BatchDeleteById
// @Description: 批量删除用户
// @receiver u
// @param ctx
// @param ids
// @param data
// @return error
func (u *UserDao) BatchDeleteById(ctx context.Context, ids []int64, data map[string]interface{}) error {
	err := u.getSession(ctx).Model(&model.UserModel{}).Where("id in ?", ids).Updates(data).Error
	return err
}

// FindById
// @Description: 按用户ID查询信息
// @receiver u
// @param ctx
// @param id
// @return *model.UserModel
// @return error
func (u *UserDao) FindById(ctx context.Context, id int64) (*model.UserModel, error) {
	var user model.UserModel
	err := u.getSession(ctx).Where("id = ?", id).First(&user).Error
	if err != nil {
		if errors.Is(err, gorm.ErrRecordNotFound) {
			return nil, nil
		}
		return nil, err
	}
	return &user, nil
}

// FindByName
// @Description: 按账户名称查询用户信息
// @receiver u
// @param ctx
// @param name
// @return []*model.UserModel
// @return error
func (u *UserDao) FindByName(ctx context.Context, name string) (*model.UserModel, error) {
	var user *model.UserModel
	err := u.getSession(ctx).
		Where("username = ?", name).
		Where(fmt.Sprintf("%s=?", u.columns.Deleted), 0).
		First(&user).
		Error
	if err != nil {
		if errors.Is(err, gorm.ErrRecordNotFound) {
			return nil, nil
		}
		return nil, err
	}
	return user, err
}

// FindByMobile
// @Description: 按手机号码查询用户信息
// @receiver u
// @param ctx
// @param mobile
// @return *model.UserModel
// @return error
func (u *UserDao) FindByMobile(ctx context.Context, mobile string) (*model.UserModel, error) {
	var user *model.UserModel
	err := u.getSession(ctx).
		Where(fmt.Sprintf("%s=?", u.columns.Mobile), mobile).
		Where(fmt.Sprintf("%s=?", u.columns.Deleted), 0).
		First(&user).
		Error
	if err != nil {
		if errors.Is(err, gorm.ErrRecordNotFound) {
			return nil, nil
		}
		return nil, err
	}
	return user, nil
}

// GetUserList
// @Description: 用户列表
// @receiver u
// @param ctx
// @param userName
// @param status
// @return []*model.UserModel
// @return error
func (u *UserDao) GetUserList(ctx context.Context, userName string, status int32, deptId, page, limit int64) (map[string]interface{}, error) {
	// 总记录数
	var total int64
	var users []*model.UserQueryModel
	db := u.getSession(ctx)
	{
		if strings.TrimSpace(userName) != "" {
			db = db.Where("username=?", userName)
		}
		if status != -1 {
			db = db.Where("status=?", status)
		}
		if deptId != -1 {
			db = db.Where("dept_id=?", deptId)
		}
		db.Where("deleted=?", 0).
			Order("id desc").
			Find(&users).Count(&total).Limit(1)
	}
	if total == 0 {
		return map[string]interface{}{
			"page":       page,
			"totalPage":  int64(0),
			"totalCount": total,
			"pageSize":   limit,
			"data":       make([]*model.UserQueryModel, 0),
		}, nil
	}
	// 计算总的分页数
	pageCount := math.Ceil(float64(total) / float64(limit))
	pageCountStr := strconv.FormatFloat(pageCount, 'f', 0, 64)
	pageCountInt, err := strconv.ParseInt(pageCountStr, 10, 64)
	if err != nil {
		return nil, err
	}

	// 偏移量
	offset := (page - 1) * limit

	db = u.getSession(ctx)
	{
		if strings.TrimSpace(userName) != "" {
			db = db.Where("sys_user.username=?", userName)
		}
		if status != -1 {
			db = db.Where("sys_user.status=?", status)
		}
		if deptId != -1 {
			db = db.Where("sys_user.dept_id=?", deptId)
		}
	}
	err = db.Where("sys_user.deleted=?", 0).
		Joins("left join sys_role on sys_user.role_id = sys_role.id").
		Joins("left join sys_department on sys_user.dept_id = sys_department.id").
		Select("sys_user.*, sys_role.name AS roleName, sys_department.name AS deptName").
		Limit(int(limit)).
		Offset(int(offset)).
		Order("id DESC").
		Find(&users).
		Error

	pageMap := map[string]interface{}{
		"page":       page,
		"totalPage":  pageCountInt,
		"totalCount": total,
		"pageSize":   limit,
		"data":       users,
	}

	return pageMap, err
}

// UpdateUserById
// @Description: 更新用户信息
// @receiver u
// @param ctx
// @param id
// @param user
// @return error
func (u *UserDao) UpdateUserById(ctx context.Context, id int64, user map[string]interface{}) error {
	idQuery := fmt.Sprintf("%s=?", u.columns.Id)
	err := u.getSession(ctx).Model(&model.UserModel{}).Where(idQuery, id).Updates(user).Error
	return err
}

// FindUserByMobile
// @Description: 按手机号码查询用户
// @receiver u
// @param ctx
// @param mobile
// @return *model.UserModel
// @return error
func (u *UserDao) FindUserByMobile(ctx context.Context, mobile string) (*model.UserModel, error) {
	var user *model.UserModel
	mobileQuery := fmt.Sprintf("%s=?", u.columns.Mobile)
	err := u.getSession(ctx).Where(mobileQuery, mobile).First(&user).Error
	if err != nil {
		if errors.Is(err, gorm.ErrRecordNotFound) {
			return nil, nil
		}
		return nil, err
	}
	return user, nil
}
